home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HAM Radio 3.2
/
Ham Radio Version 3.2 (Chestnut CD-ROMs)(1993).ISO
/
packet
/
n17jsrc
/
command.asm
< prev
next >
Wrap
Assembly Source File
|
1990-12-11
|
11KB
|
500 lines
.MODEL MEMMOD,C
LOCALS
%MACS
.LALL
extrn pwait: far
.DATA
db 4096 dup(?)
cstack label byte
.CODE
dbase dw @Data
segoff struc
offs dw ?
segm dw ?
segoff ends
main_subr dw ?
their_8h dd ?
their_10h dd ?
their_13h dd ?
their_1Bh dd ?
their_21h dd ?
their_23h dd ?
their_24h dd ?
their_28h dd ?
dos_segment dw ? ;segment of internal DOS flags
indos_offset dw ? ;offset of INDOS flag
errflag_offset dw ? ;offset of critical error flag
program_status db 0 ;popup status
flag_10h db 0 ;status of interrupt 10h
flag_13h db 0 ;status of interrupt 13h
zflag db ? ;save and restore critical error.
dos_version db ? ;dos major version.
main_countdown db 20
ss_register dw ? ;SS register storage
sp_register dw ? ;SP register storage
my_psp dw ? ;our PSP.
their_psp dw ? ;PSP segment storage
tick_counter dw ?
indos_counter dw ?
errflag_counter dw ?
status_counter dw ?
bp_counter dw ?
main_counter dw ?
their_dta dd ?
;
;------------------------------------------------------------------------------
;Interrupt 8 handling routine.
;------------------------------------------------------------------------------
timer:
pushf ;call BIOS routine
call their_8h
inc tick_counter
cmp program_status,0 ;are we already running?
jne timer_status ;yes, then suspend ticking.
cmp flag_10h,0 ;video flag set?
jne timer_exit ;yes, then exit
cmp flag_13h,0 ;disk flag set?
jne timer_exit ;yes, then exit
push es ;save ES and DI
push di
mov es,dos_segment ;check INDOS flag
mov di,indos_offset
cmp byte ptr es:[di],0
jne timer_indos ;exit if it's set
mov di,errflag_offset ;check critical error flag
cmp byte ptr es:[di],0
jne timer_errflag ;exit if it's set
mov main_subr,offset cycle
call main ;call body of program
pop di
pop es
timer_exit:
iret
timer_indos:
inc indos_counter
pop di ;restore registers
pop es
iret
timer_errflag:
inc errflag_counter
pop di ;restore registers
pop es
iret
timer_status:
inc status_counter
iret
;
;------------------------------------------------------------------------------
;Interrupt 10h handling routine.
;------------------------------------------------------------------------------
video:
pushf ;push flags onto stack
inc flag_10h ;increment flag
call their_10h ;call BIOS routine
dec flag_10h ;decrement flag
iret
;
;------------------------------------------------------------------------------
;Interrupt 13h handling routine.
;------------------------------------------------------------------------------
my_13:
pushf ;push flags onto stack
inc flag_13h ;set 'busy' flag
call their_13h ;call BIOS routine
pushf ;save output flags
dec flag_13h ;clear flag
popf ;restore output flags
retf 2 ;exit without destroying flags
;
;------------------------------------------------------------------------------
;Interrupt 28h handling routine.
;------------------------------------------------------------------------------
my_28:
pushf ;call original routine
call their_28h
inc bp_counter
cmp program_status,0 ;are we already running?
jne bp_exit ;yes, don't enter it again.
cmp flag_10h,0 ;video flag set?
jne bp_exit ;yes, then exit
cmp flag_13h,0 ;disk flag set?
jne bp_exit ;yes, then exit
push es ;save ES and DI
push di
mov es,dos_segment ;check critical error flag
mov di,errflag_offset
cmp byte ptr es:[di],0
pop di ;clean up the stack
pop es
jne bp_errflag
mov main_subr,offset cycle
call main ;call main routine
bp_exit:
iret ;done - exit
bp_errflag:
inc errflag_counter
iret ;done - exit
;
;------------------------------------------------------------------------------
;Interrupt 21h handling routine.
;------------------------------------------------------------------------------
my_21:
pushf ;save the flags
or ah,ah ;Doing function zero?
je jump_to_dos ;If yes, take the jump
cmp ah,4bh ;Doing EXEC function?
je jump_to_dos ;If yes, take the jump
popf
pushf
call cs:their_21h ;Do the DOS function
pushf ;Save the result flags
cmp cs:program_status,0 ;are we already running?
jne no_recursion ;yes, don't recurse.
dec cs:main_countdown
jne no_recursion
mov cs:main_countdown,20
mov main_subr,offset cycle
call main ;Safe to access disk now
no_recursion:
popf ;Recover DOS result flags
sti ;Must return with interrupts on
retf 2 ;Return with DOS result flags
jump_to_dos:
popf
jmp cs:their_21h
;
;------------------------------------------------------------------------------
;Interrupt 24h handling routine (DOS 3.X only).
;------------------------------------------------------------------------------
my_24:
mov al,3 ;fail the call in progress
ioexit:
iret ;give control back to DOS
cycle:
xor ax,ax ;push a null pointer.
push ax
push ax
call pwait
add sp,4
ret
;
;------------------------------------------------------------------------------
;MAIN is the routine called periodically.
;------------------------------------------------------------------------------
main:
inc main_counter
mov program_status,1 ;set program active flag
cli ;make sure interrupts are off
mov ss_register,ss ;save stack registers
mov sp_register,sp
mov ss,cs:dbase ; establish interrupt data segment
mov sp,offset cstack
sti ;enable interrupts
push ax
push bx
push cx
push dx
push si
push di
push ds
push es
push bp
;
;Set DS and ES segment registers.
;
push cs ;set DS to code segment
pop ds
assume ds:seg dos_version
;
;Save the current active PSP address and activate this PSP.
;
mov zflag,0 ;clear flag
cmp dos_version,2 ;DOS version 2.X?
jne main5
mov es,dos_segment ;point ES:DI to INDOS
mov di,indos_offset
cmp byte ptr es:[di],0 ;INDOS clear?
je main5 ;yes, then branch
mov di,errflag_offset ;point ES:DI to error flag
cmp byte ptr es:[di],0 ;critical error flag clear?
jne main5 ;no, then branch
mov byte ptr es:[di],1 ;set critical error flag manually
mov zflag,1 ;set change flag
main5:
mov ah,51h ;get current PSP segment
int 21h
mov their_psp,bx ;save it
mov ah,50h ;make this the active PSP
mov bx,my_psp
int 21h
cmp zflag,0 ;ZFLAG clear?
je main6 ;yes, then branch
mov di,errflag_offset ;point ES:DI to error flag
mov byte ptr es:[di],0 ;restore error flag value
main6:
;
;Reset the interrupt 1Bh, 23h, and 24h vectors.
;
call ioset ;reset interrupt vectors
;
;Save the current dta and subdirectory
;
mov ah,2fh ;get disk transfer address
int 21h
mov their_dta.segm,es
mov their_dta.offs,bx
;
;Call the commutator loop of net until nothing gets queued up.
;
mov ds,cs:dbase ; establish interrupt data segment
assume ds:nothing
call main_subr
;
;Restore the current dta and subdirectory
;
lds dx,their_dta
mov ah,1ah
int 21h
;
;Restore interrupt vectors and former active PSP.
;
mov ah,50h ;restore active PSP label
mov bx,their_psp
int 21h
call ioreset ;restore interrupt vectors
;
;Restore registers and stack before exit.
;
pop bp ;restore registers and exit
pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
cli ;interrupts off
mov ss,ss_register ;switch to original stack
mov sp,sp_register
sti ;interrupts on
mov program_status,0 ;clear status flag
ret
;
intset:
;enter with al = interrupt number, cs:dx = offset of new interrupt,
; cs:di -> place to store old interrupt.
push es ;get the old interrupt into es:bx
push ds ;now set the new interrupt to ds:dx.
mov bx,cs
mov ds,bx
mov ah,35h
int 21h
mov [di].segm,es ;and store it into ds:di.
mov [di].offs,bx
mov ah,25h
int 21h
pop ds
pop es
ret
intreset:
;enter with al = interrupt number, di -> old interrupt.
push ds
mov ah,25h
lds dx,cs:[di]
int 21h
pop ds
ret
;------------------------------------------------------------------------------
;IOSET vectors interrupts 1Bh, 23h and 24h to internal handlers. IORESET
;restores the original vector values.
;------------------------------------------------------------------------------
ioset:
mov al,1bh
mov di,offset their_1Bh
mov dx,offset ioexit
call intset
mov al,23h
mov di,offset their_23h
mov dx,offset ioexit
call intset
mov al,24h
mov di,offset their_24h
mov dx,offset my_24
call intset
ret
;
ioreset:
mov al,24h
mov di,offset their_24h
call intreset
mov al,23h
mov di,offset their_23h
call intreset
mov al,1Bh
mov di,offset their_1Bh
call intreset
ret
public start_back
start_back proc
;
;Remember our psp.
;
mov ah,51h ;get current PSP segment
int 21h
mov my_psp,bx ;save it
;
;Determine which version of DOS is running.
;
init3:
mov ah,30h ;DOS function 30h
int 21h
mov dos_version,al ;major version number
;
;Get and save the address of the INDOS flag.
;
mov ah,34h ;function 34h
int 21h ;get address
mov dos_segment,es ;save segment
mov indos_offset,bx ;save offset
;
;Get and save the address of the critical error flag.
;
mov ax,3E80h ;CMP opcode
mov cx,2000h ;max search length
mov di,bx ;start at INDOS address
init4:
repne scasw ;do the search
jcxz init5 ;branch if search failed
cmp byte ptr es:[di+5],0BCh ;verify this is it
je found ;branch if it is
jmp init4 ;resume loop if it's not
init5:
mov cx,2000h ;search again
inc bx ;search odd addresses this time
mov di,bx
init6:
repne scasw ;look for the opcode
jcxz notfound ;not found if loop expires
cmp byte ptr es:[di+5],0BCh ;verify this is it
je found
jmp init6
notfound:
xor ax,ax
ret
found:
mov ax,es:[di] ;get flag offset address
mov errflag_offset,ax ;save it
;
;Save and replace all required interrupt vectors.
;
mov al,08h
mov dx,offset timer
mov di,offset their_8h
call intset
mov al,10h
mov dx,offset video
mov di,offset their_10h
call intset
mov al,13h
mov dx,offset my_13
mov di,offset their_13h
call intset
mov al,28h
mov dx,offset my_28
mov di,offset their_28h
call intset
mov al,21h
mov dx,offset my_21
mov di,offset their_21h
call intset
mov ax,1
ret
start_back endp
public stop_back
stop_back proc
mov cs:program_status,1
mov al,08h
mov di,offset their_8h
call intreset
mov al,10h
mov di,offset their_10h
call intreset
mov al,13h
mov di,offset their_13h
call intreset
mov al,28h
mov di,offset their_28h
call intreset
mov al,21h
mov di,offset their_21h
call intreset
mov cs:program_status,0
mov dx,ds
mov ax,offset tick_counter
ret
stop_back endp
end